package top.dyzmj.detty.core.utils;

import top.dyzmj.detty.core.buffer.ByteBuf;

import java.nio.ByteOrder;

/**
 * 描述: 处理ByteBuf相关的工具
 *
 * @author dongYu
 * @date 2021/11/18
 */
public class ByteBufUtil {

	private ByteBufUtil() {
	}

	/**
	 * {@link ByteBuf#indexOf(int, int, byte)}的默认实现。
	 */
	public static int indexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) {
		if (fromIndex <= toIndex) {
			return firstIndexOf(buffer, fromIndex, toIndex, value);
		} else {
			return lastIndexOf(buffer, fromIndex, toIndex, value);
		}
	}

	private static int firstIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) {
		fromIndex = Math.max(fromIndex, 0);
		if (fromIndex >= toIndex || buffer.capacity() == 0) {
			return -1;
		}

		for (int i = fromIndex; i < toIndex; i++) {
			if (buffer.getByte(i) == value) {
				return i;
			}
		}

		return -1;
	}

	private static int lastIndexOf(ByteBuf buffer, int fromIndex, int toIndex, byte value) {
		fromIndex = Math.min(fromIndex, buffer.capacity());
		if (fromIndex < 0 || buffer.capacity() == 0) {
			return -1;
		}

		for (int i = fromIndex - 1; i >= toIndex; i--) {
			if (buffer.getByte(i) == value) {
				return i;
			}
		}

		return -1;
	}

	public static int hashCode(ByteBuf buffer) {
		final int aLen = buffer.readableBytes();
		final int intCount = aLen >>> 2;
		final int byteCount = aLen & 3;

		int hashCode = 1;
		int arrayIndex = buffer.readerIndex();
		if (buffer.order() == ByteOrder.BIG_ENDIAN) {
			for (int i = intCount; i > 0; i--) {
				hashCode = 31 * hashCode + buffer.getInt(arrayIndex);
				arrayIndex += 4;
			}
		} else {
			for (int i = intCount; i > 0; i--) {
				hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex));
				arrayIndex += 4;
			}
		}

		for (int i = byteCount; i > 0; i--) {
			hashCode = 31 * hashCode + buffer.getByte(arrayIndex++);
		}

		if (hashCode == 0) {
			hashCode = 1;
		}

		return hashCode;
	}

	public static int swapInt(int value) {
		return Integer.reverseBytes(value);
	}

	public static boolean equals(ByteBuf bufferA, ByteBuf bufferB) {
		if (bufferA == bufferB) {
			return true;
		}
		final int aLen = bufferA.readableBytes();
		if (aLen != bufferB.readableBytes()) {
			return false;
		}
		return equals(bufferA, bufferA.readerIndex(), bufferB, bufferB.readerIndex(), aLen);
	}

	public static boolean equals(ByteBuf a, int aStartIndex, ByteBuf b, int bStartIndex, int length) {


		if (a.writerIndex() - length < aStartIndex || b.writerIndex() - length < bStartIndex) {
			return false;
		}

		final int longCount = length >>> 3;
		final int byteCount = length & 7;

		if (a.order() == b.order()) {
			for (int i = longCount; i > 0; i--) {
				if (a.getLong(aStartIndex) != b.getLong(bStartIndex)) {
					return false;
				}
				aStartIndex += 8;
				bStartIndex += 8;
			}
		} else {
			for (int i = longCount; i > 0; i--) {
				if (a.getLong(aStartIndex) != swapLong(b.getLong(bStartIndex))) {
					return false;
				}
				aStartIndex += 8;
				bStartIndex += 8;
			}
		}

		for (int i = byteCount; i > 0; i--) {
			if (a.getByte(aStartIndex) != b.getByte(bStartIndex)) {
				return false;
			}
			aStartIndex++;
			bStartIndex++;
		}

		return true;
	}

	/**
	 * 切换指定的64位长整数的字节顺序
	 */
	public static long swapLong(long value) {
		return Long.reverseBytes(value);
	}

}
